import {EventEmitter} from "events";
import Clock from '@gamestdio/timer'
import {Timeline} from "@gamestdio/timeline";
import {Client} from "../Client";

export abstract class AbstractRoom<T = any> extends EventEmitter {
  public clock: Clock = new Clock(true);
  public timeline: Timeline;
  public roomId: string;
  public clients: Client[] = [];
  public maxClients: number = Infinity;
  public state: T;


  public abstract onMessage(client: Client, data: any): void;

  // Optional abstract methods
  public onInit?(options: any): void;

  public onJoin?(client: Client): void | Promise<any>;

  public onLeave?(client: Client): void | Promise<any>;

  public onDispose?(): void | Promise<any>;

  public onFrame?(dt: number): void;

  public start() {
    this.clock.setInterval(() => {
      this.onFrame(15)
    }, 15)
  }

  public broadcast(type: any, data: any, except?: Client) {
    if (except) {
      this.clients.filter(value => value.sessionId !== except.sessionId).forEach(value => {
        value.send(type, data)
      })
    } else {
      this.clients.forEach(value => value.send(type, data))
    }
  }

  private _join(client: Client) {
    if (this.clients.length >= this.maxClients) {
      throw new Error('room capacity is not enough')
    }
    client.room = this;
    this.clients.push(client);
    return this.onJoin(client);
  }

  private _leave(client: Client) {
    console.log('leave: ', client.user)
    for (let i = 0; i < this.clients.length; i++) {
      if (client.sessionId === client.sessionId) {
        this.clients.splice(i, 1);
        break;
      }
    }
    console.log('remain: ', this.clients.length)
  }
}